<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>OnMessage</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
</head>
<body>

<h1>OnMessage()</h1>

<p>Specifies a <a href="../Functions.htm">function</a> or <a href="../objects/Functor.htm">function object</a> to call automatically when the script receives the specified message.</p>

<pre class="Syntax">OnMessage(MsgNumber [, Function, MaxThreads])</pre>
<h3>Parameters</h3>
<dl>

  <dt>MsgNumber</dt>
  <dd><p>The number of the message to monitor or query, which should be between 0 and 4294967295 (0xFFFFFFFF). If you do not wish to monitor a <a href="../misc/SendMessageList.htm">system message</a> (that is, one below 0x400), it is best to choose a number greater than 4096 (0x1000) to the extent you have a choice. This reduces the chance of interfering with messages used internally by current and future versions of AutoHotkey.</p></dd>

  <dt>Function</dt>
  <dd><p>A <a href="../Functions.htm">function</a>'s name or, in <span class="ver">[v1.1.20+]</span>, a <a href="../objects/Functor.htm">function object</a>. To pass a literal function name, it must be enclosed in quotes.</p>
  <p>How the function is registered and the return value of OnMessage depend on whether this parameter is a string or a function object.  See <a href="#Name_v_Object">Function Name vs Object</a> for details.</p>
  </dd>

  <dt>MaxThreads <span class="ver">[v1.0.47+]</span></dt>
  <dd><p><a name="MaxThreads"></a>This integer is normally omitted, in which case the monitor function is limited to one <a href="../misc/Threads.htm">thread</a> at a time. This is usually best because otherwise, the script would process messages out of chronological order whenever the monitor function interrupts itself. Therefore, as an alternative to <em>MaxThreads</em>, consider using <em>Critical</em> as described <a href="#Critical">below</a>.</p>
  <p><span class="ver">[v1.1.20+]:</span> By default, when multiple functions are registered for a single <em>MsgNumber</em>, they are called in the order that they were registered. To register a function to be called before any previously registered functions, specify a negative value for <em>MaxThreads</em>. For example, <code>OnMessage(Msg, Fn, -2)</code> registers <code>Fn</code> to be called before any other functions previously registered for <em>Msg</em>, and allows <em>Fn</em> a maximum of 2 threads. However, if the function is already registered, the order will not change unless it is unregistered and then re-registered.</p></dd>

</dl>

<h3 id="Name_v_Object">Function Name vs Object</h3>
<p>OnMessage's return value and behavior depends on whether the <em>Function</em> parameter is a function name or an object.</p>

<h4>Function Name</h4>
<p>For backward compatibility, at most one function can be registered by name to monitor each unique <em>MsgNumber</em> -- this is referred to as the "legacy" monitor.</p>
<p>When the legacy monitor is first registered, whether it is called before or after previously registered monitors depends on the <em>MaxThreads</em> parameter. Updating the monitor to call a different function does not affect the order unless the monitor is unregistered first.</p>
<p>This registers or updates the current legacy monitor for <em>MsgNumber</em> (omit the quote marks if passing a variable):</p>
<pre class="Syntax">Name := OnMessage(MsgNumber, "FunctionName")</pre>
<p>The return value is one of the following:</p>
<ul>
  <li>An empty string on <a href="#Failure">failure</a>.</li>
  <li>The name of the previous function, if there was one.</li>
  <li>Otherwise, the name of the new function.</li>
</ul>
<p>This unregisters the current legacy monitor for <em>MsgNumber</em> (if any) and returns its name (blank if none):</p>
<pre class="Syntax">Name := OnMessage(MsgNumber, "")</pre>
<p>This returns the name of the current legacy monitor for <em>MsgNumber</em> (blank if none):</p>
<pre class="Syntax">Name := OnMessage(MsgNumber)</pre>

<h4>Function Object</h4>
<p>Any number of <a href="../objects/Functor.htm">function objects</a> (including <a href="../objects/Func.htm">normal functions</a>) can monitor a given <em>MsgNumber</em>.</p>
<p>Either of these two lines registers a function object to be called <strong>after</strong> any previously registered functions:</p>
<pre class="Syntax">
OnMessage(MsgNumber, FuncObj)     <em>; Option 1</em>
OnMessage(MsgNumber, FuncObj, 1)  <em>; Option 2 (MaxThreads = 1)</em>
</pre>
<p>This registers a function object to be called <strong>before</strong> any previously registered functions:</p>
<pre class="Syntax">OnMessage(MsgNumber, FuncObj, -1)</pre>
<p>To unregister a function object, specify 0 for <em>MaxThreads</em>:</p>
<pre class="Syntax">OnMessage(MsgNumber, FuncObj, 0)</pre>

<h3 id="Failure">Failure</h3>
<p>Failure occurs when <em>Function</em>:</p>
<ol>
  <li>is not an object, the name of a user-defined function, or an empty string;</li>
  <li>is known to require more than four parameters; or</li>
  <li>in v1.0.48.05 or older, has any <a href="../Functions.htm#ByRef">ByRef</a> or <a href="../Functions.htm#optional">optional</a> parameters.</li>
</ol>
<p>In v1.1.19.03 or older, failure also occurs if the script attempts to monitor a new message when there are already 500 messages being monitored.</p>
<p>If <em>Function</em> is an object, an exception is thrown on failure. Otherwise, an empty string is returned.</p>

<h3>The Function's Parameters</h3>
<p>A <a href="../Functions.htm">function</a> assigned to monitor one or more messages can accept up to four parameters:</p>
<pre>MyMessageMonitor(wParam, lParam, msg, hwnd)
{
    ... body of function...
}</pre>
<p>Although the names you give the parameters do not matter, the following information is sequentially assigned to them:</p>
<p>Parameter #1: The message's WPARAM value.<br>
Parameter #2: The message's LPARAM value.<br>
Parameter #3: The message number, which is useful in cases where a function monitors more than one message.<br>
Parameter #4: The HWND (unique ID) of the window or control to which the message was sent. The HWND can be used with <a href="../misc/WinTitle.htm#ahk_id">ahk_id</a>.</p>
<p>WPARAM and LPARAM are unsigned 32-bit integers (from 0 to 2<sup>32</sup>-1) or signed 64-bit integers (from -2<sup>63</sup> to 2<sup>63</sup>-1) depending on whether the exe running the script is 32-bit or 64-bit. For 32-bit scripts, if an incoming parameter is intended to be a signed integer, any negative numbers can be revealed by following this example:</p>
<pre>if (A_PtrSize = 4 &amp;&amp; wParam &gt; 0x7FFFFFFF)  <em>; Checking <a href="../Variables.htm#PtrSize">A_PtrSize</a> ensures the script is 32-bit.</em>
    wParam := -(~wParam) - 1</pre>
<p>You can omit one or more parameters from the end of the list if the corresponding information is not needed. For example, a function defined as <code>MyMsgMonitor(wParam, lParam)</code> would receive only the first two parameters, and one defined as <code>MyMsgMonitor()</code> would receive none of them.</p>

<h3>Additional Information Available to the Function</h3>
<p>In addition to the parameters received above, the function may also consult the values in the following built-in variables:</p>
<ul>
  <li><a href="../Variables.htm#Gui">A_Gui</a>: Blank unless the message was sent to a GUI window or control, in which case A_Gui is the <a href="Gui.htm#MultiWin">Gui Window number</a> (this window is also set as the function's <a href="Gui.htm#DefaultWin">default GUI window</a>).</li>
  <li><a href="../Variables.htm#GuiControl">A_GuiControl</a>: Blank unless the message was sent to a GUI control, in which case it contains the control's variable name or other value as described at <a href="../Variables.htm#GuiControl">A_GuiControl</a>. Some controls never receive certain types of messages. For example, when the user clicks a <a href="GuiControls.htm#Text">text control</a>, the operating system sends WM_LBUTTONDOWN to the parent window rather than the control; consequently, A_GuiControl is blank.</li>
  <li><a href="../Variables.htm#GuiX">A_GuiX</a> and <a href="../Variables.htm#GuiX">A_GuiY</a>: Both contain -2147483648 if the incoming message was sent via <a href="PostMessage.htm">SendMessage</a>. If it was sent via <a href="PostMessage.htm">PostMessage</a>, they contain the mouse cursor's coordinates (relative to the screen) at the time the message was posted.</li>
  <li><a href="../Variables.htm#EventInfo">A_EventInfo</a>: Contains 0 if the message was sent via SendMessage. If sent via PostMessage, it contains the <a href="../Variables.htm#TickCount">tick-count time</a> the message was posted.</li>
</ul>
<p>A monitor function's <a href="../misc/WinTitle.htm#LastFoundWindow">last found window</a> starts off as the parent window to which the message was sent (even if it was sent to a control). If the window is hidden but not a GUI window (such as the script's main window), turn on <a href="DetectHiddenWindows.htm">DetectHiddenWindows</a> before using it. For example:</p>
<pre>DetectHiddenWindows On
MsgParentWindow := WinExist()  <em>; This stores the unique ID of the window to which the message was sent.</em></pre>

<h3>What the Function Should <em>Return</em></h3>
<p>If a monitor function uses <a href="Return.htm">Return</a> without any parameters, or it specifies a blank value such as &quot;&quot; (or it never uses Return at all), the incoming message goes on to be processed normally when the function finishes. The same thing happens if the function <a href="Exit.htm">Exits</a> or causes a runtime error such as <a href="Run.htm">running</a> a nonexistent file. By contrast, returning an integer causes it to be sent immediately as a reply; that is, the program does not process the message any further. For example, a function monitoring WM_LBUTTONDOWN (0x201) may return an integer to prevent the target window from being notified that a mouse click has occurred. In many cases (such as a message arriving via <a href="PostMessage.htm">PostMessage</a>), it does not matter which integer is returned; but if in doubt, 0 is usually safest.</p>
<p>The range of valid return values depends on whether the exe running the script is 32-bit or 64-bit. Non-empty return values must be between -2<sup>31</sup> and 2<sup>32</sup>-1 for 32-bit scripts (<code><a href="../Variables.htm#PtrSize">A_PtrSize</a> = 4</code>) and between -2<sup>63</sup> and 2<sup>63</sup>-1 for 64-bit scripts (<code><a href="../Variables.htm#PtrSize">A_PtrSize</a> = 8</code>).</p>
<p><span class="ver">[v1.1.20+]:</span> If there are multiple functions monitoring a given message number, they are called one by one until one returns a non-empty value.</p>

<h3 id="Remarks">General Remarks</h3>
<p>Unlike a normal function-call, the arrival of a monitored message calls the function as a new <a href="../misc/Threads.htm">thread</a>. Because of this, the function starts off fresh with the default values for settings such as <a href="SendMode.htm">SendMode</a> and <a href="DetectHiddenWindows.htm">DetectHiddenWindows</a>. These defaults can be changed in the <a href="../Scripts.htm#auto">auto-execute section</a>.</p>
<p>Messages sent to a control (rather than being posted) are not monitored because the system routes them directly to the control behind the scenes. This is seldom an issue for system-generated messages because most of them are posted.</p>
<p>Any script that calls OnMessage anywhere is automatically <a href="_Persistent.htm">persistent</a>. It is also single-instance unless <a href="_SingleInstance.htm">#SingleInstance</a> has been used to override that.</p>
<p><a name="Critical"></a>If a message arrives while its function is still running due to a previous arrival of the same message, the function will not be called again (except if <a href="#MaxThreads">MaxThreads</a> is greater than 1); instead, the message will be treated as unmonitored. If this is undesirable, a message greater than or equal to 0x312 can be buffered until its function completes by specifying <a href="Critical.htm">Critical</a> as the first line of the function. Alternatively, <a href="Thread.htm">Thread Interrupt</a> can achieve the same thing as long as it lasts long enough for the function to finish. By contrast, a message less than 0x312 cannot be buffered by Critical or Thread Interrupt (however, in v1.0.46+, Critical may help because it checks messages <a href="Critical.htm#Interval">less often</a>, which gives the function more time to finish). The only way to guarantee that no such messages are missed is to ensure the function finishes in under 6 milliseconds (though this limit can be raised via <a href="Critical.htm#Interval"><em>Critical 30</em></a>). One way to do this is to have it queue up a future thread by <a href="PostMessage.htm">posting</a> to its own script a monitored message number higher than 0x312. That message's function should use <a href="Critical.htm">Critical</a> as its first line to ensure that its messages are buffered.</p>
<p>If a monitored message that is numerically less than 0x312 arrives while the script is absolutely uninterruptible -- such as while a <a href="Menu.htm">menu</a> is displayed, a <a href="SetKeyDelay.htm">KeyDelay</a>/<a href="SetMouseDelay.htm">MouseDelay</a> is in progress, or the clipboard is being <a href="_ClipboardTimeout.htm">opened</a> -- the message's function will not be called and the message will be treated as unmonitored.  By contrast, a monitored message of 0x312 or higher will be buffered during  these uninterruptible periods; that is, its function will be called when the script becomes interruptible.</p>
<p>If a monitored message numerically less than 0x312 arrives while the script is uninterruptible merely due to the settings of <a href="Thread.htm">Thread Interrupt</a> or <a href="Critical.htm">Critical</a>, the current thread will be interrupted so that the function can be called. By contrast, a monitored message of 0x312 or higher will be buffered until the thread finishes or becomes interruptible.</p>
<p>The <a href="../misc/Threads.htm">priority</a> of OnMessage threads is always 0. Consequently, no messages are monitored or buffered when the current thread's priority is higher than 0.</p>
<p>Caution should be used when monitoring system messages (those below 0x400). For example, if a monitor function does not finish quickly, the response to the message might take longer than the system expects, which might cause side-effects. Unwanted behavior may also occur if a monitor function returns an integer to suppress further processing of a message, but the system expected different processing or a different response.</p>
<p>When the script is displaying a system dialog such as <a href="MsgBox.htm">MsgBox</a>, any message posted to a control is not monitored. For example, if the script is displaying a MsgBox and the user clicks a button in a GUI window, the WM_LBUTTONDOWN message is sent directly to the button without calling the monitor function.</p>
<p>Although an external program may post messages directly to a script's thread via PostThreadMessage() or other API call, this is not recommended because the messages would be lost if the script is displaying a system window such as a <a href="MsgBox.htm">MsgBox</a>. Instead, it is usually best to post or send the messages to the script's main window or one of its GUI windows.</p>
<h3>Related</h3>
<p><a href="RegisterCallback.htm">RegisterCallback()</a>, <a href="OnExit.htm">OnExit</a>, <a href="OnClipboardChange.htm">OnClipboardChange</a>, <a href="PostMessage.htm">Post/SendMessage</a>, <a href="../Functions.htm">Functions</a>, <a href="../misc/SendMessageList.htm">List of Windows Messages</a>, <a href="../misc/Threads.htm">Threads</a>, <a href="Critical.htm">Critical</a>, <a href="DllCall.htm">DllCall()</a></p>
<h3>Examples</h3>
<pre class="NoIndent"><em>; Example: The following is a working script that monitors mouse clicks in a GUI window.
; Related topic: <a href="Gui.htm#GuiContextMenu">GuiContextMenu</a></em>

Gui, Add, Text,, Click anywhere in this window.
Gui, Add, Edit, w200 vMyEdit
Gui, Show
OnMessage(0x201, &quot;WM_LBUTTONDOWN&quot;)
return

WM_LBUTTONDOWN(wParam, lParam)
{
    X := lParam &amp; 0xFFFF
    Y := lParam &gt;&gt; 16
    if A_GuiControl
        Control := &quot;`n(in control &quot; . A_GuiControl . &quot;)&quot;
    ToolTip You left-clicked in Gui window #%A_Gui% at client coordinates %X%x%Y%.%Control%
}

GuiClose:
ExitApp</pre>

<pre class="NoIndent"><a name="shutdown"></a><em>; Example: The following script detects system shutdown/logoff and allows you to abort it (this is
; reported NOT to work on Windows Vista and later).
; Related topic: <a href="OnExit.htm">OnExit</a></em>

<em>; The following DllCall is optional: it tells the OS to shut down this script <i>first</i> (prior to all other applications).</em>
DllCall(&quot;kernel32.dll\SetProcessShutdownParameters&quot;, UInt, 0x4FF, UInt, 0)
OnMessage(0x11, &quot;WM_QUERYENDSESSION&quot;)
return

WM_QUERYENDSESSION(wParam, lParam)
{
    ENDSESSION_LOGOFF = 0x80000000
    if (lParam &amp; ENDSESSION_LOGOFF)  <em>; User is logging off.</em>
        EventType = Logoff
    else  <em>; System is either shutting down or restarting.</em>
        EventType = Shutdown
    MsgBox, 4,, %EventType% in progress.  Allow it?
    IfMsgBox Yes
        return true  <em>; Tell the OS to allow the shutdown/logoff to continue.</em>
    else
        return false  <em>; Tell the OS to abort the shutdown/logoff.</em>
}</pre>

<pre class="NoIndent"><em>; Example: Have a script receive a custom message and up to two numbers from some other script or program
; (to send strings rather than numbers, see the example after this one).</em>

OnMessage(0x5555, &quot;MsgMonitor&quot;)
OnMessage(0x5556, &quot;MsgMonitor&quot;)

MsgMonitor(wParam, lParam, msg)
{
    <em>; Since returning quickly is often important, it is better to use a ToolTip than</em>
    <em>; something like MsgBox that would prevent the function from finishing:</em>
    ToolTip Message %msg% arrived:`nWPARAM: %wParam%`nLPARAM: %lParam%
}

<em>; The following could be used inside some other script to run the function inside the above script:</em>
SetTitleMatchMode 2
DetectHiddenWindows On
if WinExist(&quot;Name of Receiving Script.ahk ahk_class AutoHotkey&quot;)
    PostMessage, 0x5555, 11, 22  <em>; The message is sent  to the &quot;<a href="../misc/WinTitle.htm#LastFoundWindow">last found window</a>&quot; due to WinExist() above.</em>
DetectHiddenWindows Off  <em>; Must not be turned off until after PostMessage.</em></pre>

<pre class="NoIndent"><a name="SendString"></a><em>; Example: Send a string of any length from one script to another.  This is a working example.
; To use it, save and run both of the following scripts then press Win+Space to show an
; InputBox that will prompt you to type in a string.</em>

<em>; Save the following script as &quot;<strong>Receiver.ahk</strong>&quot; then launch it:</em>
#SingleInstance
OnMessage(0x4a, &quot;Receive_WM_COPYDATA&quot;)  <em>; 0x4a is WM_COPYDATA</em>
return

Receive_WM_COPYDATA(wParam, lParam)
{
    StringAddress := NumGet(lParam + 2*A_PtrSize)  <em>; Retrieves the CopyDataStruct's lpData member.</em>
    CopyOfData := StrGet(StringAddress)  <em>; Copy the string out of the structure.</em>
    <em>; Show it with ToolTip vs. MsgBox so we can return in a timely fashion:</em>
    ToolTip %A_ScriptName%`nReceived the following string:`n%CopyOfData%
    return true  <em>; Returning 1 (true) is the traditional way to acknowledge this message.</em>
}

<em>; Save the following script as &quot;<strong>Sender.ahk</strong>&quot; then launch it.  After that, press the Win+Space hotkey.</em>
TargetScriptTitle = Receiver.ahk ahk_class AutoHotkey

#space::  <em>; Win+Space hotkey. Press it to show an InputBox for entry of a message string.</em>
InputBox, StringToSend, Send text via WM_COPYDATA, Enter some text to Send:
if ErrorLevel  <em>; User pressed the Cancel button.</em>
    return
result := Send_WM_COPYDATA(StringToSend, TargetScriptTitle)
if result = FAIL
    MsgBox SendMessage failed. Does the following WinTitle exist?:`n%TargetScriptTitle%
else if result = 0
    MsgBox Message sent but the target window responded with 0, which may mean it ignored it.
return

Send_WM_COPYDATA(ByRef StringToSend, ByRef TargetScriptTitle)  <em>; ByRef saves a little memory in this case.
; This function sends the specified string to the specified window and returns the reply.
; The reply is 1 if the target window processed the message, or 0 if it ignored it.</em>
{
    VarSetCapacity(CopyDataStruct, 3*A_PtrSize, 0)  <em>; Set up the structure's memory area.</em>
    <em>; First set the structure's cbData member to the size of the string, including its zero terminator:</em>
    SizeInBytes := (StrLen(StringToSend) + 1) * (A_IsUnicode ? 2 : 1)
    NumPut(SizeInBytes, CopyDataStruct, A_PtrSize)  <em>; OS requires that this be done.</em>
    NumPut(&amp;StringToSend, CopyDataStruct, 2*A_PtrSize)  <em>; Set lpData to point to the string itself.</em>
    Prev_DetectHiddenWindows := A_DetectHiddenWindows
    Prev_TitleMatchMode := A_TitleMatchMode
    DetectHiddenWindows On
    SetTitleMatchMode 2
    SendMessage, 0x4a, 0, &amp;CopyDataStruct,, %TargetScriptTitle%  <em>; 0x4a is WM_COPYDATA. Must use Send not Post.</em>
    DetectHiddenWindows %Prev_DetectHiddenWindows%  <em>; Restore original setting for the caller.</em>
    SetTitleMatchMode %Prev_TitleMatchMode%         <em>; Same.</em>
    return ErrorLevel  <em>; Return SendMessage's reply back to our caller.</em>
}</pre>

<pre class="NoIndent"><em>; Example: See the <a href="../scripts/WinLIRC.htm">WinLIRC client script</a> for a demonstration of how to use OnMessage() to receive
; notification when data has arrived on a network connection.</em></pre>

</body>
</html>
